﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using Shell32;  //Reference Microsoft Shell Controls and Automation on the Com tab.

namespace WSPDocGenerator
{
    public static class ExtractWSP
    {
        
        // Use the Shell.Application COM object to extract the contents of the sourceCabPath and put the contents into
        // the destinationDirectory. Support is included for cab files with sub directory hierarchies.
        public static bool ExpandCabFile(string CabFile, string DestDir)
        {
            // Verify input parameters
            if (!Directory.Exists(DestDir)) 
                return false;

            if (!File.Exists(CabFile))
                return false;

            FileInfo cabInfo = new FileInfo(CabFile);
            if (cabInfo.Extension != ".cab")
                return false;

            //Create folder where to expand cab
            string cabFolder = DestDir + "\\" + cabInfo.Name.Replace(cabInfo.Extension, "");
            if (Directory.Exists(cabFolder))
                Directory.Delete(cabFolder, true);

            System.Threading.Thread.Sleep(0);
            Directory.CreateDirectory(cabFolder);
            
            Shell sh = new Shell();
            Folder fldr = sh.NameSpace(cabFolder);
            int cabNameLength = CabFile.Length;
            string cachedDestDir = null;
            Folder relativeDest = null;

            // Process each item in the cab. Determine if the destination
            // is a sub directory and create if necessary.
            foreach (FolderItem f in sh.NameSpace(CabFile).Items())
            { 
                int lastPathIndex = f.Path.LastIndexOf("\\");
                
                // If the file inside the zip file should be extracted
                // to a subfolder, then we need to reset the destination
                if (cabNameLength < lastPathIndex)
                {
                    string relativePath = f.Path.Substring((cabNameLength + 1), (lastPathIndex - cabNameLength));
                    string relativeDestDir = cabFolder + "\\" + relativePath;

                    if (!Directory.Exists(relativeDestDir))
                        Directory.CreateDirectory(relativeDestDir);

                    if (relativeDestDir != cachedDestDir)
                    {
                        relativeDest = sh.NameSpace(relativeDestDir);
                        cachedDestDir = relativeDestDir;
                    }

                    relativeDest.CopyHere(f, 0);
                }
                else
                    fldr.CopyHere(f, 0); 
            }
                
            return true;
        }

    }
}
